import { expect, test } from 'vitest';

import { docComment } from './DocComment';
import { genericParameter } from './GenericParameter';
import { method } from './Method';
import { namedType } from './NamedType';
import { parameter } from './Parameter';
import { stringify } from './stringify';

const A = namedType('A');
const B = namedType('B');

test('name only', () => {
  const m = method('doThings');
  expect(stringify(m)).toMatchInlineSnapshot(`"doThings(): void"`);
});

test('with return type', () => {
  const m = method('doThings').setReturnType(A);
  expect(stringify(m)).toMatchInlineSnapshot(`"doThings(): A"`);
});

test('with doc comment', () => {
  const m = method('doThings').setDocComment(docComment('Does things'));
  expect(stringify(m)).toMatchInlineSnapshot(`
    "/**
     * Does things
     */
    doThings(): void"
  `);
});

test('with parameter', () => {
  const m = method('doThings').addParameter(parameter('foo', A));
  expect(stringify(m)).toMatchInlineSnapshot(`"doThings(foo: A): void"`);
});

test('with multiple parameters', () => {
  const m = method('doThings').addParameter(parameter('foo', A)).addParameter(parameter('foo', B));
  expect(stringify(m)).toMatchInlineSnapshot(`"doThings(foo: A, foo: B): void"`);
});

test('with generic parameter', () => {
  const m = method('doThings').addGenericParameter(genericParameter('T'));
  expect(stringify(m)).toMatchInlineSnapshot(`"doThings<T>(): void"`);
});

test('with multiple generic parameters', () => {
  const m = method('doThings')
    .addGenericParameter(genericParameter('T'))
    .addGenericParameter(genericParameter('U'));
  expect(stringify(m)).toMatchInlineSnapshot(`"doThings<T, U>(): void"`);
});
